﻿namespace WebPacker.Tests.Packs
{
	using System;
	using NUnit.Framework;
	using WebPacker.Filters;
	using WebPacker.Packs;
	using WebPacker.Packs.Resources;
	using WebPacker.Packs.Watchers;
	using WebPacker.VersionGenerators;

	[TestFixture]
	public class PackTest
	{
		[Test]
		public void ConstructorTest()
		{
			var resources = GetResources();
			var pack = new Pack(PackType.JavaScript, "jsPack", resources, null);
			Assert.AreEqual(PackType.JavaScript, pack.PackType);
			Assert.AreEqual("jsPack", pack.Name);
			Assert.That(pack.Resources, Is.EquivalentTo(resources));
			Assert.IsNull(pack.VersionGenerator);
			Assert.IsEmpty(pack.Version);
			Assert.IsFalse(pack.Monitoring);
			Assert.IsNull(pack.Filter);
		}

		[Test]
		public void FullConstructorTest()
		{
			var filter = new YuiCssMinifier();
			var generator = new Md5VersionGenerator();
			var resources = GetResources();
			var pack = new Pack(PackType.Css, "css", resources, filter, new CompositeWatcher(), generator, "1.0.1");
			Assert.AreEqual(PackType.Css, pack.PackType);
			Assert.AreEqual("css", pack.Name);
			Assert.That(pack.Resources, Is.EquivalentTo(resources));
			Assert.AreSame(filter, pack.Filter);
			Assert.AreSame(generator, pack.VersionGenerator);
			Assert.AreEqual("1.0.1", pack.Version);
		}

		[Test]
		public void ConstructorNameMissedTest()
		{
			Assert.Throws<ArgumentNullException>(() => new Pack(PackType.JavaScript, null, GetResources(), null, null, null, "1.1"));
		}
		
		[Test]
		public void ConstructorResourcesMissedTest()
		{
			Assert.Throws<ArgumentNullException>(() => new Pack(PackType.JavaScript, "jsPack", null, new YuiCssMinifier(), null, null, null));
		}

		[Test]
		public void ConstructorInvalidFilterTest()
		{
			Assert.Throws<ArgumentException>(() => new Pack(PackType.JavaScript, "jsPack", GetResources(), new YuiCssMinifier(), null, null, "1.1"));
		}

		[Test]
		public void GetSourceContentTest()
		{
			var pack = GetTestPack();
			Assert.AreEqual("hello, world!", pack.GetSourceContent());
		}

		[Test]
		public void GetContentTest()
		{
			var pack = GetTestPack();
			Assert.AreEqual("HELLO, WORLD!", pack.GetContent());
		}

		[Test]
		public void GetLastModifiedTest()
		{
			var pack = GetTestPack();
			Assert.AreEqual(new DateTime(2100, 12, 11), pack.GetLastModifiedTime());
		}

		[Test]
		public void UpdateVersionTest()
		{
			var pack = GetTestPack();
			pack.UpdateVersion();
			Assert.AreEqual("3adbbad1791fbae3ec908894c4963870", pack.Version);
		}

		public void WatcherVersionTest()
		{
			var resources = new ContentResource[] { new ContentResource("test", "test") };
			var pack = new Pack(PackType.JavaScript, "pack1", resources, null, new ContentWatcher(), new Md5VersionGenerator(), null);
			resources[0].SetContent("hello, world!");
			Assert.AreEqual("3adbbad1791fbae3ec908894c4963870", pack.Version);
		}

		private Pack GetTestPack()
		{
			return new Pack(PackType.JavaScript, "pack1", GetResources(), new TestUpperFilter(), new ContentWatcher(), new Md5VersionGenerator(), "1.0.1");
		}
		
		private ContentResource[] GetResources()
		{
			return new ContentResource[]
			{
				new ContentResource("res1", "hello, ", new DateTime(2100, 12, 11)),
				new ContentResource("res2", "world!")
			};
		}

		private class TestUpperFilter : IFilter
		{
			public string Name { get; set; }

			public PackType PackType
			{
				get { return PackType.JavaScript; }
			}

			public string Apply(string content)
			{
				return content;
			}

			public string ApplyToCombined(string combinedContent)
			{
				return combinedContent.ToUpper();
			}
		}
	}
}
